package com.bestv.search.spider.iqiyi.sync;

import com.bestv.search.spider.model.Person;
import com.bestv.search.spider.service.PersonManager;
import com.bestv.search.spider.util.SpiderConst;
import com.bestv.search.spider.util.SpiderUtil;
import com.bestv.search.spider.util.StringUtil;
import com.bestv.search.spider.youku.sync.YouKuPersonSyncer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Hibernate;
import org.htmlparser.Node;
import org.htmlparser.NodeFilter;
import org.htmlparser.Parser;
import org.htmlparser.Tag;
import org.htmlparser.filters.HasAttributeFilter;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.tags.ImageTag;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.scheduling.quartz.QuartzJobBean;

import java.io.File;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

public class IQiyiPersonSyncer extends QuartzJobBean {

    private static boolean isRunning = false;
    private final Log log = LogFactory.getLog(IQiyiPersonSyncer.class);
    private String infoFolder;
    private PersonManager personManager;

    @Override
    protected void executeInternal(JobExecutionContext arg0) throws JobExecutionException {
        if (!isRunning) {
            try {
                isRunning = true;
                log.info(" Sync person avatar from IQiyi begin @" + new Date());

                // Set running flag
                Calendar c = Calendar.getInstance();
                String fileFolderPath = getFileFolderByDateTime(c.getTime());

                // remove over 7 days' files.
                String parentFolder = fileFolderPath + File.separator + SpiderConst.POINT + SpiderConst.POINT
                        + File.separator;
                String[] overdueFolders = SpiderUtil.getOver7DaysFolders(parentFolder);
                if (overdueFolders != null) {
                    for (String path : overdueFolders) {
                        SpiderUtil.deleteDirectory(parentFolder + path);
                    }
                }

                String isRunningFile = fileFolderPath + File.separator + SpiderConst.ISRUNNING_FLAG_FILE;
                String dupliPersonNameFile = fileFolderPath + File.separator + SpiderConst.DUPLICATE_PERSON_NAME_FILE;
                SpiderUtil.createFile(isRunningFile);

                List<Person> syncPersons = personManager.getByNullAvatar_Iqiyi();

                // Sync begin
                syncAllAvatar(syncPersons, dupliPersonNameFile);

                personManager.saveList(syncPersons);

                // Writes videos info to file as JSON format
                String file = fileFolderPath + File.separator + SpiderConst.ALL_PERSONS_FILE;
                List<Person> allPerson = personManager.getAll();
                for (Person person : allPerson) {
                    String json = YouKuPersonSyncer.convertToJson(person, personManager);
                    SpiderUtil.addTextToFile(json, file);
                }
                SpiderUtil.deleteFile(isRunningFile);

                log.info(" Sync person avatar from IQiyi eng @" + new Date());
            } catch (Exception e) {
                log.error("Sync person info failed from IQiyi " + e);
                e.printStackTrace();
            } finally {
                isRunning = false;
            }
        }
    }

    @SuppressWarnings("deprecation")
    private void syncAllAvatar(List<Person> list, String dupliPersonNameFile) {
        for (Person p : list) {
            String nameEncode = URLEncoder.encode(p.getName());
            StringBuffer url = StringUtil.buildBuffer(new String[]{SpiderConst.IQIYI_SEARCH_URL, nameEncode});
            String response = new SpiderUtil().sendRequest(url.toString());
            if (response != null && !response.equals(SpiderConst.EMPTY)) {
                byte[] avatar = getAvatar(response, p, dupliPersonNameFile);
                if (avatar != null) {
                    p.setAvatar_iqiyi(Hibernate.createBlob(avatar));
                    personManager.update(p);
                }
            }

            // Sleep 3 seconds to don't make it
            // access too often
            try {
                Thread.sleep(3 * 1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private byte[] getAvatar(String response, Person person, String dupliPersonNameFile) {
        byte[] result = null;

        Parser p = new Parser();
        try {
            p.setInputHTML(response);

            // gets all person divs
            NodeFilter personDivFilter = new HasAttributeFilter(SpiderConst.CLASS, SpiderConst.IQIYI_PERSON_DIV_CLASS);
            NodeList nodes = p.parse(personDivFilter);

            if (nodes != null && nodes.size() > 0) {
                NodeFilter infoDivFilter = new HasAttributeFilter(SpiderConst.CLASS, SpiderConst.IQIYI_CMT60_CLASS);
                NodeList cmt604Divs = new NodeList();
                nodes.elementAt(0).collectInto(cmt604Divs, infoDivFilter);

                int minLength = Math.min(cmt604Divs.size(), 5);
                List<PersonBaseInfo> list = new ArrayList<PersonBaseInfo>();
                for (int i = 0; i < minLength; i++) {
                    Node div = cmt604Divs.elementAt(i);
                    // Gets name
                    String name = null;
                    NodeFilter cmtInfoF14DivFilter = new HasAttributeFilter(SpiderConst.CLASS,
                            SpiderConst.IQIYI_CMT_INFOF14_DIV_CLASS);
                    NodeList cmtInfoF14Divs = new NodeList();
                    div.collectInto(cmtInfoF14Divs, cmtInfoF14DivFilter);
                    if (cmtInfoF14Divs.size() > 0) {
                        NodeFilter aFilter = new TagNameFilter(SpiderConst.A);
                        NodeList aTags = new NodeList();
                        cmtInfoF14Divs.elementAt(0).collectInto(aTags, aFilter);
                        if (aTags.size() > 0) {
                            name = aTags.elementAt(0).toPlainTextString().trim();
                        }
                    }

                    // gets birthday
                    String birthdayText = null;
                    NodeFilter cmtInfoDivFilter = new HasAttributeFilter(SpiderConst.CLASS,
                            SpiderConst.IQIYI_CMT_INFO_DIV_CLASS);
                    NodeList cmtInfoDivs = new NodeList();
                    div.collectInto(cmtInfoDivs, cmtInfoDivFilter);
                    if (cmtInfoDivs.size() > 0) {
                        String cmt_info = cmtInfoDivs.elementAt(0).toPlainTextString();
                        if (cmt_info != null && cmt_info.split(SpiderConst.BACK_SLANT).length > 2) {
                            birthdayText = cmt_info.split(SpiderConst.BACK_SLANT)[1];
                        }
                    }

                    if (name != null && name.equals(person.getName())) {
                        PersonBaseInfo personBaseInfo = new PersonBaseInfo();
                        personBaseInfo.name = name;
                        personBaseInfo.birthday = birthdayText == null ? SpiderConst.EMPTY : birthdayText.trim();

                        // gets person url
                        NodeFilter cmtHeadDivFilter = new HasAttributeFilter(SpiderConst.CLASS,
                                SpiderConst.IQIYI_CMT_HEAD_DIV_CLASS);
                        NodeList cmtHeadDivs = new NodeList();
                        div.collectInto(cmtHeadDivs, cmtHeadDivFilter);
                        if (cmtHeadDivs.size() > 0) {
                            NodeFilter aFilter = new TagNameFilter(SpiderConst.A);
                            NodeList aTags = new NodeList();
                            cmtHeadDivs.elementAt(0).collectInto(aTags, aFilter);
                            if (aTags.size() > 0) {
                                String herf = ((Tag) aTags.elementAt(0)).getAttribute(SpiderConst.HERF);
                                personBaseInfo.personDetailURL = herf;
                                list.add(personBaseInfo);
                            }
                        }
                    }
                }

                // Gets avatars
                if (list != null && list.size() > 0) {
                    String url = SpiderConst.EMPTY;
                    if (list.size() == 1) {
                        url = list.get(0).personDetailURL;
                    } else {
                        for (PersonBaseInfo personBaseInfo : list) {
                            if (personBaseInfo.birthday != null && personBaseInfo.birthday.equals(person.getBirthday())) {
                                url = personBaseInfo.personDetailURL;
                                break;
                            }
                        }
                    }

                    if (url != null && !url.equals(SpiderConst.EMPTY)) {
                        String personDetail = new SpiderUtil().sendRequest(url);
                        if (personDetail != null && !personDetail.equals(SpiderConst.EMPTY)) {
                            Parser personPage = new Parser();

                            // get pic
                            personPage.setInputHTML(personDetail);
                            NodeFilter profLeftDivFilter = new HasAttributeFilter(SpiderConst.CLASS,
                                    SpiderConst.IQIYI_PROF_LEFT_DIV_CLASS);
                            NodeList leftDivNodes = personPage.parse(profLeftDivFilter);
                            if (leftDivNodes == null || leftDivNodes.size() == 0) {
                                personPage.setInputHTML(personDetail);
                                profLeftDivFilter = new HasAttributeFilter(SpiderConst.CLASS,
                                        SpiderConst.IQIYI_STARCARD_IMG_DIV_CLASS);
                                leftDivNodes = personPage.parse(profLeftDivFilter);
                            }

                            if (leftDivNodes.size() > 0) {
                                NodeFilter imgFilter = new TagNameFilter(SpiderConst.IMG);
                                NodeList imgTags = new NodeList();
                                leftDivNodes.elementAt(0).collectInto(imgTags, imgFilter);
                                if (imgTags.size() > 0) {
                                    ImageTag img = (ImageTag) imgTags.elementAt(0);
                                    String src = img.getAttribute(SpiderConst.SRC);
                                    if (src != null && !src.equals(SpiderConst.EMPTY)) {
                                        // Don't end with default image
                                        if (!src.endsWith("img195_260.gif")) {
                                            result = SpiderUtil.getBytesByURL(src);
                                        } else {
                                            result = null;
                                        }
                                    }
                                }
                            }
                        }
                    } else {
                        if (list.size() != 0 && list.size() > 1) {
                            SpiderUtil.addTextToFile(person.getName(), dupliPersonNameFile);
                        }
                    }
                }
            }
        } catch (ParserException e) {
            log.error("Get short avatar failed from iqiyi ");
            log.error(e);
            e.printStackTrace();
        }
        return result;
    }

    private String getFileFolderByDateTime(Date date) {
        String personFolder = this.getInfoFolder() + File.separator + SpiderConst.PERSON;
        File folder = new File(personFolder);
        if (!folder.exists()) {
            folder.mkdir();
        }

        personFolder = personFolder + File.separator + SpiderConst.YOUKU;
        folder = new File(personFolder);
        if (!folder.exists()) {
            folder.mkdir();
        }

        SimpleDateFormat format = new SimpleDateFormat(SpiderConst.DATETIME_FORMAT);
        String dateTimeFolder = personFolder + File.separator + format.format(date);
        folder = new File(dateTimeFolder);
        if (!folder.exists()) {
            folder.mkdir();
        }
        return dateTimeFolder;
    }

    public PersonManager getPersonManager() {
        return personManager;
    }

    public void setPersonManager(PersonManager personManager) {
        this.personManager = personManager;
    }

    public String getInfoFolder() {
        return infoFolder;
    }

    public void setInfoFolder(String infoFolder) {
        this.infoFolder = infoFolder;
    }

    class PersonBaseInfo {
        String name;
        String birthday;
        String personDetailURL;
    }
}